package com.atguigu.gmall.seckill.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.model.activity.SeckillGoods;
import com.atguigu.gmall.model.activity.SeckillOrder;
import com.atguigu.gmall.model.activity.UserRecode;
import com.atguigu.gmall.mq.config.RabbitService;
import com.atguigu.gmall.seckill.mapper.SeckillMapper;
import com.atguigu.gmall.seckill.mapper.SeckillOrderMapper;
import com.atguigu.gmall.seckill.service.SeckillService;
import org.apache.catalina.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 秒杀服务的实现类
 */
@Service
public class SeckillServiceImpl implements SeckillService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RabbitService rabbitService;
    @Autowired
    private SeckillOrderMapper seckillOrderMapper;
    @Autowired
    private SeckillMapper seckillMapper;

    /**
     * 秒杀商品列表
     *
     * @param time
     * @return
     */
    @Override
    public List<SeckillGoods> getSeckillGoods(String time) {
        List<SeckillGoods> seckillGoodsList = redisTemplate.boundHashOps("SeckillGoods_"+time).values();
        return seckillGoodsList;
    }

    /**
     * 秒杀商品详情
     *
     * @param time
     * @param id
     * @return
     */
    @Override
    public SeckillGoods getSeckillGood(String time, String id) {
        SeckillGoods seckillGoods = (SeckillGoods)redisTemplate.boundHashOps("SeckillGoods_"+ time).get(id);
        return seckillGoods;
    }

    /**
     * 用户排队下单
     *
     * @param time
     * @param skuId
     * @param userId
     * @return
     */
    @Override
    public UserRecode addOrder(String time, String skuId, String userId) {
        //记录用户的排队信息
        UserRecode userRecode = new UserRecode();
        //防止用户重复排队
        Long increment = redisTemplate.boundValueOps("SeckillUserQueue_" + userId).increment(1);
        if (increment > 1){
            userRecode.setStatus(3);
            userRecode.setMsg("重复排队！！！！");
            return userRecode;
        }
        userRecode.setUsername(userId);
        userRecode.setCreateTime(new Date());
        //状态为排队中
        userRecode.setStatus(1);
        userRecode.setGoodsId(skuId);
        userRecode.setTime(time);
        userRecode.setNum(1);
        //将用户的派对信息存入redis中去
        redisTemplate.boundValueOps("SeckillStatus_"+ userId).set(userRecode);
        //发送消息进行异步下单
        rabbitService.sendMessage("seckill_exchange","seckill.order.add",
                JSONObject.toJSONString(userRecode));
        //返回用户排队的结果
        return userRecode;
    }

    /**
     * 查询用户的排队信息
     *
     * @param userId
     * @return
     */
    @Override
    public UserRecode getUserRecode(String userId) {
        return (UserRecode)redisTemplate.boundValueOps("SeckillStatus_"+ userId).get();
    }

    /**
     * 查询秒杀订单的详情
     *
     * @param useranme
     * @param orderId
     * @return
     */
    @Override
    public List<SeckillOrder> getSeckillOrderList(String useranme, String orderId) {
        if (StringUtils.isEmpty(orderId)){
            //查询所有秒杀订单的列表
            return redisTemplate.boundHashOps("SeckillOrder_"+ useranme).values();
        }else {
            List<SeckillOrder> seckillOrders = new ArrayList<>();
            //获取指定的秒杀订单详情
            SeckillOrder seckillOrder = (SeckillOrder)redisTemplate.boundHashOps("SeckillOrder_"+useranme).get(orderId);
            seckillOrders.add(seckillOrder);
            return seckillOrders;
        }
    }


    /**
     * 支付成功
     *
     * @param map
     */
    @Override
    public void paySuccess(Map<String, String> map) {
        //先获取微信的附加参数
        String attach = map.get("attach");
        //若为空则获取支付宝的附加参数
        if (StringUtils.isEmpty(attach)){
            attach = map.get("passback_params");
        }
        //类型转换
        Map<String,String> attachMap = JSONObject.parseObject(attach, Map.class);
        String username = attachMap.get("username");
        String outTradeNo = map.get("out_trade_no");
        //从redis中获取订单的信息
        SeckillOrder seckillOrder =
                (SeckillOrder)redisTemplate.boundHashOps("SeckillOrder_" + username).get(outTradeNo);
        //判断前置状态
        if (seckillOrder != null && seckillOrder.getStatus().equals("0")){
            //修改订单的支付状态
            seckillOrder.setStatus("1");
            seckillOrder.setPayTime(new Date());
            //map获取微信的订单支付单号
            String otn = map.get("transaction_id");
            if (StringUtils.isEmpty(otn)){
                otn = map.get("trade_no");
            }
            seckillOrder.setOutTradeNo(otn);
            //修改redis中订单的状态
            redisTemplate.boundHashOps("SeckillOrder_"+username).put(outTradeNo,seckillOrder);
            //将订单的信息存入数据库
            seckillOrderMapper.insert(seckillOrder);
            //排队标识删除掉
            redisTemplate.delete("SeckillUserQueue_"+username);
            //排队状态可以删掉了
            redisTemplate.delete("SeckillStatus_"+username);
        }

    }

    /**
     * 支付失败
     *
     * @param map
     */
    @Override
    public void payFail(Map<String, String> map) {
        //先获取微信的附加参数
        String attach = map.get("attach");
        //若为空则获取支付宝的附加参数
        if (StringUtils.isEmpty(attach)){
            attach = map.get("passback_params");
        }
        Map<String,String> attachMap = JSONObject.parseObject(attach, Map.class);
        String username = attachMap.get("username");
        String outTradeNo = map.get("out_trade_no");
        //从redis中获取订单的信息
        SeckillOrder seckillOrder = (SeckillOrder)redisTemplate.boundHashOps("SeckillOrder_"+username).get(outTradeNo);
        //判断前置状态
        if (seckillOrder != null && seckillOrder.getStatus().equals("0")){
            //修改订单的支付状态
            seckillOrder.setStatus("2");
            //修改redis中订单的状态
            redisTemplate.boundHashOps("SeckillOrder_" + username).put(outTradeNo, seckillOrder);
            //将订单的信息存入数据库
            seckillOrderMapper.insert(seckillOrder);
            //库存回滚----1.redis回滚 2. 数据库回滚
            UserRecode userRecode = (UserRecode)redisTemplate.boundValueOps("SeckillStatus_" + username).get();
            rollBackSeckillGoodsNum(userRecode.getGoodsId(), userRecode.getTime(), userRecode.getNum());
            //排队标识删除掉
            redisTemplate.delete("SeckillUserQueue_" + username);
            //排队状态删除掉
            redisTemplate.delete("SeckillStatus_" + username);
        }
    }

    /**
     * 回滚秒杀商品的库存
     * @param skuId
     * @param time
     * @param num
     */
    private void rollBackSeckillGoodsNum(String skuId, String time, Integer num) {
       //从redis中获取商品的数据
        SeckillGoods seckillGoods = (SeckillGoods)redisTemplate.boundHashOps("SeckillGoods_" + time).get(skuId);
        if (seckillGoods == null ){
            //商品已经售罄了--更新数据库中的库存数据
            seckillMapper.updateSeckillGoodsStock(skuId,num);
        }else {
            //redis中海油数据--更新redis中的库存数据
            String[] seckillGoodsQueue = getSeckillGoodsQueue(skuId,num);
            redisTemplate.boundListOps("seckillGoodsQueue_" + skuId).leftPushAll(seckillGoodsQueue);
            //回滚库存的对象
            redisTemplate.boundHashOps("SeckillGoodsStockNum").increment(skuId,num);
        }

    }

    /**
     * 构建商品库存个数长度的数组
     * @param goodsId
     * @param stockCount
     * @return
     */
    private String[] getSeckillGoodsQueue(String goodsId, Integer stockCount) {
        //构建一个库存长度的数组
        String[] ids = new String[stockCount];
        //元素填充
        for (int i = 0; i < stockCount; i++) {
            ids[i] = goodsId;
        }
        //返回数据
        return ids;
    }


}
